#include "cpu/reg.h"

static const int parity_table [] = {
	0, 1, 0, 1,
	1, 0, 1, 0,
	0, 1, 0, 1,
	1, 0, 1, 0
};

void update_eflags_pf_zf_sf(uint32_t result) {
	uint8_t temp = result & 0xff;
	cpu.eflags.PF = parity_table[temp & 0xf] ^ parity_table[temp >> 4];
	cpu.eflags.ZF = (result == 0);
	cpu.eflags.SF = result >> 31;
}

bool check_cc(uint8_t condition) {
    switch (condition) {
    case 0x0: return cpu.eflags.OF;                   // SETO/JO
    case 0x1: return !cpu.eflags.OF;                  // SETNO/JNO
    case 0x2: return cpu.eflags.CF;                   // SETB/JB
    case 0x3: return !cpu.eflags.CF;                  // SETNB/JNB
    case 0x4: return cpu.eflags.ZF;                   // SETZ/JZ
    case 0x5: return !cpu.eflags.ZF;                  // SETNZ/JNZ
    case 0x6: return cpu.eflags.CF || cpu.eflags.ZF;  // SETBE/JBE
    case 0x7: return !cpu.eflags.CF && !cpu.eflags.ZF; // SETNBE/JNBE
    case 0x8: return cpu.eflags.SF;                   // SETS/JS
    case 0x9: return !cpu.eflags.SF;                  // SETNS/JNS
    case 0xA: return cpu.eflags.PF;                   // SETP/JP
    case 0xB: return !cpu.eflags.PF;                  // SETNP/JNP
    case 0xC: return cpu.eflags.SF != cpu.eflags.OF;  // SETL/JL
    case 0xD: return cpu.eflags.SF == cpu.eflags.OF;  // SETNL/JNL
    case 0xE: return cpu.eflags.ZF || (cpu.eflags.SF != cpu.eflags.OF); // SETLE/JLE
    case 0xF: return !cpu.eflags.ZF && (cpu.eflags.SF == cpu.eflags.OF); // SETNLE/JNLE
    default: return false;
    }
}

const char* get_cc_name(uint8_t condition) {
    static const char* names[] = {
        "o", "no", "b", "nb", "z", "nz", "be", "nbe",
        "s", "ns", "p", "np", "l", "nl", "le", "nle"
    };
    return names[condition];
}

